package br.unifor.g2cl;

import java.io.IOException;
import java.net.SocketAddress;
import java.util.logging.Logger;

import net.sf.jgcs.Annotation;
import net.sf.jgcs.ClosedSessionException;
import net.sf.jgcs.DataSession;
import net.sf.jgcs.ExceptionListener;
import net.sf.jgcs.GroupConfiguration;
import net.sf.jgcs.Message;
import net.sf.jgcs.MessageListener;
import net.sf.jgcs.Service;
import net.sf.jgcs.ServiceListener;
import net.sf.jgcs.UnsupportedServiceException;

/**
 * <div style="text-align:justify;"> New DataSession class, which works like an
 * adapter [Gamma et al. 1995] between the G2CL services and the original
 * DataSession used by the jGCS plug-ins. </div> <br/>
 * <div style="text-align:justify;"> The main responsibility of this new class
 * is to intercept all message transmission calls made to the plug-in by the
 * application and then execute the necessary transformations to convert between
 * a message of type G2CLMessage and another message of type Message. In this
 * way, all G2CL services must rely only on MarshalDataSession for message
 * transmission (instead of the original DataSession class of jGCS). </div>
 * 
 * @author Leandro Sales (leandro.shp@gmail.com)
 * 
 */
public class MarshalDataSession implements IMarshalDataSession, MessageListener {

	private static Logger logger = Logger.getLogger(MarshalDataSession.class
			.getName());

	private MessageListener listener;

	private DataSession data;

	public MarshalDataSession(DataSession data) {
		this.data = data;
	}

	public void close() {
		data.close();
	}

	public Message createMessage() throws ClosedSessionException {
		return new G2CLMessage();
	}

	public GroupConfiguration getGroup() {
		return data.getGroup();
	}

	public void multicast(Message msg, Service service, Object cookie, Annotation... annotation) throws IOException,
			UnsupportedServiceException {

		data.multicast(createMessage(msg), service, cookie, annotation);
	}

	public void send(Message msg, Service service,Object cookie,SocketAddress destination, Annotation... annotation)
			throws IOException, UnsupportedServiceException {
		data.send(createMessage(msg), service, cookie, destination, annotation);
	}

	/**
	 * Convert the Message passed as a parameter into the message provided by
	 * the real DataSession
	 * 
	 * @param msg
	 * @throws ClosedSessionException
	 */
	private Message createMessage(Message msg) throws ClosedSessionException {
		Message m = data.createMessage();
		m.setPayload(msg.getPayload());
		SocketAddress sender = msg.getSenderAddress();
		if (sender != null) {
			m.setSenderAddress(sender);
		}
		return m;
	}

	public Object onMessage(Message msg) {
		Object ret = null;
		if (listener != null) {
			ret = listener.onMessage(G2CLMessage.fromMessage(msg));
		}
		return ret;
	}

	/* ************************************************************************* */
	/*  **************** LISTENERS ***************** */
	/* ************************************************************************* */

	public void setExceptionListener(ExceptionListener exception)
			throws ClosedSessionException {
		data.setExceptionListener(exception);
	}

	public void setMessageListener(MessageListener listener)
			throws ClosedSessionException {
		this.listener = listener;
		data.setMessageListener(this);
	}

	public void setServiceListener(ServiceListener listener)
			throws ClosedSessionException {
		data.setServiceListener(listener);
	}
}
